﻿using AutoMapper;
using HikRcsService.Common;
using HikRcsService.Models;
using Newtonsoft.Json;
using Serilog;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using WCS_Entity.Dto.RcsDto;
using WCS_Service.DomianService.Interface;
using WCS_Service.DomianService.Models;
using WCS_Service.Enums;
using WCS_Service.Interface;
using WCS_Service.Models;
using WCS_Service.Models.SerialNetModel;
using WCS_Service.RcsServices;
using WCS_Service.RcsServices.Interfaces;
using WCS_Service.Services;
using WCS_Utility.ConstString;
using static System.Runtime.InteropServices.JavaScript.JSType;

namespace WCS_Service.DomianService.AutoEquipmentDomain
{
    /// <summary>
    /// RCS服务类
    /// </summary>
    public class RCSDomainService: IRCSDomainService
    {
        #region 属性
        public ConcurrentDictionary<string, RcsServiceModel> RcsInfo = new();

        public event Func<string,string,string, Task> ExitComRoadWayChange;
        public event Func<string, string, string, Task> EnterComRoadWayChange;
        public event Func<string, string, Task> TaskEndChange;
        public event Func<string, string, string, string, Task> TaskPauseChange;
        public event Func<string, string,Task> ChargeReportChange;
        public event Func<string,RollerReadInfoModel, Task> RollerInfoChange;
        public event Func<string, WarnModel, Task> WarnInfoChange;
        #endregion

        private readonly IRcsApiService _rcsApiService;
        private readonly IRcsService _rcsService;
        private readonly IMapper _mapper;
        private readonly IRcsApiBuildService _rcsApiBuildService;
        //海康rcs
        private readonly IHikOpticalRcsService _hikOpticalRcsService;

        public event Func<List<AgvInfoModel>, string,string, Task> AgvInfoChange;
        public event Func<List<TaskStatusModel>, string, string, Task> TaskInfoChange;
        public event Func<List<PodBerthAndMatInfoModel>, string, string, Task> PodBerthAndMatChange;
        public event Func<List<MapInfoModel>, string, string, Task> MapInfoChange;
        public event Func<ResultModel, string, string, Task> ResultChange;
        public event Func<ResultDataModel, string, string, Task> ResultDataChange;

        public RCSDomainService(IRcsApiService rcsApiService, IMapper mapper, 
                                IRcsService rcsService,
                                IHikOpticalRcsService hikOpticalRcsService,
                                IRcsApiBuildService rcsApiBuildService)
        {
            _rcsApiService = rcsApiService;
            _rcsService = rcsService;
            _mapper = mapper;
            _rcsApiBuildService = rcsApiBuildService;
            _hikOpticalRcsService = hikOpticalRcsService;
        }

        public async Task InitRcsInfoAsync()
        {
            var rcsServices = await _rcsService.QueryAllRcsAsync();
            if (rcsServices is null || !rcsServices.Any())
            {
                return;
            }
            List<Task> initRcs = new();
            foreach (var item in rcsServices)
            {
                initRcs.Add(CreatRcsServiceModelAsync(item)); 
            }
            await Task.WhenAll(initRcs);

            _hikOpticalRcsService.RcsReciveEvent += ReciveInfoProcessAsyc;
            _hikOpticalRcsService.ServiceResultEvent += ServiceResultProcessAsync;
            _hikOpticalRcsService.RollerReciveEvent += RollerResultProcessAsync;
        }
        /// <summary>
        /// 根据透传协议类型获取对应的处理方法
        /// </summary>
        /// <param name="messageType"></param>
        /// <returns></returns>
        public async Task<Func<string,int,Task>?> GetRcsService(string messageType)
        {
            return await Task.Run(() =>
            {
                Func<string,int, Task> result;
                switch (messageType)
                {
                    case ConstStringData.SerialNet_HikRCS:
                        result = _hikOpticalRcsService.OrientedMsgAsync;
                        break;
                    default:
                        result = null;
                        break;
                };
                return result;
            });
        }
        /// <summary>
        /// 拼接AGV外设设备控制报文
        /// </summary>
        /// <param name="peripheral"></param>
        /// <param name="para"></param>
        /// <returns></returns>
        public async Task<AgvPeripheralInfoModel> StructAgvPeripheralParaAsync(string peripheral, object para)
        {
            AgvPeripheralInfoModel result = new AgvPeripheralInfoModel();

            switch (peripheral)
            {
                case ConstStringData.Promptlight_Peripheral:
                    result.data = await CreatPromptlightParaAsync(para);
                    result.type = (int)OpticalMsgType.Promptlight;
                    result.reqCode = GetreqCode();
                    break;
                case ConstStringData.Roller_Peripheral:
                    result.type = (int)OpticalMsgType.Roller;
                    result.reqCode = GetreqCode();
                    result.data = await CreatRollerParaAsync(para);
                    break;
            }
            return result;
        }

        public async Task<RcsApiResultModel> StructureRcsParaAsync(string rcs,string api,object para,bool isResult)
        {
            if (isResult)
            {
                return await ServiceResultAsync(rcs, api, para);
            }
            else
            {
                return await ServiceCallAsync(rcs, api, para);
            }
        }
        #region private
        /// <summary>
        /// 滚筒数据处理
        /// </summary>
        /// <param name="eqCode"></param>
        /// <param name="info"></param>
        /// <returns></returns>
        private async Task RollerResultProcessAsync(string eqCode,string info)
        {
            await Task.Run(() => 
            {
                var para = JsonConvert.DeserializeObject<RollerReadInfoModel>(info);
                if (para is null)
                {
                    Log.Error($"滚筒状态读取失败!");
                    return;
                }
                RollerInfoChange?.Invoke(ConstStringData.Roller_Peripheral, para);
            });
        }

        /// <summary>
        /// WCS返回光通信的访问数据
        /// </summary>
        /// <returns></returns>
        private async Task<RcsApiResultModel> ServiceResultAsync(string rcs, string api, object para)
        {
            RcsApiResultModel result = new();
            RcsServiceInfoModel rcsServiceInfoModel = new RcsServiceInfoModel();
            rcsServiceInfoModel.type = (int)OpticalMsgType.Result;
            var (reqCode, sendData) = await CreatWcsResultRcsPara(api, para);
            rcsServiceInfoModel.reqCode = reqCode;
            rcsServiceInfoModel.data = sendData is null ? null : JsonConvert.SerializeObject(sendData);
            result.info = rcsServiceInfoModel;

            return result;
        }
        /// <summary>
        /// WCS访问光通信转接的RCS服务接口
        /// </summary>
        /// <param name="rcs"></param>
        /// <param name="api"></param>
        /// <param name="para"></param>
        /// <returns></returns>
        private async Task<RcsApiResultModel> ServiceCallAsync(string rcs, string api, object para)
        {
            RcsApiResultModel result = new();
            var rcsApi = await QueryRcsApi(rcs, api);
            if (rcsApi is null)
            {
                return null;
            }
            var rcsPara = await CreatWcsRcsPara(api, para);
            if (rcsPara is null)
            {
                return null;
            }
            result.rcsApi = rcsApi;
            switch (rcs)
            {
                case ConstStringData.SerialNet_HikRCS:
                    result.info = await _hikOpticalRcsService.SplicingRCSParaAsync(rcsApi, rcsPara);
                    break;
                case ConstStringData.SerialNet_TheseusRCS:
                    break;
            }
            if (result.info is null)
            {
                return null;
            }
            return result;
        }

        private async Task<string> ServiceResultProcessAsync(RcsServiceResultModel model)
        {
            string result = "success";
            switch (model.apiName)
            {
                case HikRcsConst.agvCallback:
                    await AgvCallbackProcessAsync(model);
                    break;
                case HikRcsConst.bindNotify:
                    await BindNotifyAsync(model);
                    break;
                case HikRcsConst.applyReturnForValid:
                    await ApplyReturnForValidAsync(model);
                    break;
                case HikRcsConst.applyReturnForBin:
                    await ApplyReturnForBinAsync(model);
                    break;
                case HikRcsConst.warnCallback:
                    await WarnAsync(model);
                    break;
                case HikRcsConst.chargeReport:
                    await ChargeReportAsync(model);
                    break;
            }

            return result;
        }
        /// <summary>
        /// 充电请求
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        private async Task ChargeReportAsync(RcsServiceResultModel model)
        {
            var chargeReportInfo = model.info as ChargeRequestModel;
            if (chargeReportInfo is null)
            {
                return;
            }
            ChargeReportChange?.Invoke(model.eqCode, chargeReportInfo.reqCode);
        }
        /// <summary>
        /// 告警处理
        /// </summary>
        /// <returns></returns>
        private async Task WarnAsync(RcsServiceResultModel model)
        {
            var warnInfo = model.info as WarnModel;
            if (warnInfo is null)
            {
                return;
            }
            WarnInfoChange?.Invoke(model.eqCode,warnInfo);
        }
        /// <summary>
        /// 绑定通知处理
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        private async Task BindNotifyAsync(RcsServiceResultModel model)
        { 
            
        }
        /// <summary>
        /// 校验料箱是否可入库
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        private async Task ApplyReturnForValidAsync(RcsServiceResultModel model)
        { 
            
        }
        /// <summary>
        /// 申请回库仓位
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        private async Task ApplyReturnForBinAsync(RcsServiceResultModel model)
        { 
            
        }
        /// <summary>
        /// agv上报任务状态处理
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        private async Task AgvCallbackProcessAsync(RcsServiceResultModel model)
        {
            await Task.Run(() => 
            {
                var taskInfo = model.info as TaskExecuteStateModel;
                if (taskInfo is null)
                {
                    return;
                }
                //通过currentPositionCode字段或method判断是要出巷道还是进入巷道
                 TaskPauseChange?.Invoke(model.eqCode, taskInfo.taskCode, taskInfo.method, taskInfo.robotCode);
            });
        }
        private async Task ReciveInfoProcessAsyc(string eqCode,string reqCode,object data,string type)
        {
            switch (type)
            {
                case ConstStringData.RcsRecive_Agv:
                    await AgvQueryInfoProcessAsync(eqCode, reqCode, data);
                    break;
                case ConstStringData.RcsRecive_Map:
                    await MapQueryInfoProcessAsync(eqCode, reqCode, data);
                    break;
                case ConstStringData.RcsRecive_PodBerthAndMat:
                    await PodBerthAndMatProcessAsync(eqCode, reqCode, data);
                    break;
                case ConstStringData.RcsRecive_result:
                    await ResultProcessAsync(eqCode, reqCode, data);
                    break;
                case ConstStringData.RcsRecive_resultData: 
                    await ResultDataProcessAsync(eqCode, reqCode, data);
                    break;
                case ConstStringData.RcsRecive_Task:
                    await QueryTaskDataProcessAsync(eqCode, reqCode, data);
                    break;
            }
        }
        /// <summary>
        /// 查询任务状态处理
        /// </summary>
        /// <returns></returns>
        private async Task QueryTaskDataProcessAsync(string eqCode, string reqCode, object data)
        { 
            
        }
        private async Task ResultDataProcessAsync(string eqCode, string reqCode, object data)
        {
            var info = data as ResultDataModel;
            ResultDataChange?.Invoke(info, reqCode, eqCode);
        }
        private async Task ResultProcessAsync(string eqCode, string reqCode, object data)
        {
            var info = data as ResultModel;
            ResultChange?.Invoke(info, reqCode, eqCode);
        }
        /// <summary>
        /// 查询货架储位与物料批次关系 
        /// </summary>
        /// <returns></returns>
        private async Task PodBerthAndMatProcessAsync(string eqCode, string reqCode, object dat)
        { 
            
        }
        /// <summary>
        /// 地图同步上下文返回
        /// </summary>
        /// <param name="eqCode"></param>
        /// <param name="reqCode"></param>
        /// <param name="dat"></param>
        /// <returns></returns>
        private async Task MapQueryInfoProcessAsync(string eqCode, string reqCode, object dat)
        { 
            
        }
        /// <summary>
        /// AGV数据查询返回
        /// </summary>
        /// <returns></returns>
        private async Task AgvQueryInfoProcessAsync(string eqCode, string reqCode, object data)
        {
            await Task.Run(() => 
            {
                var resultValue = data as AgvStateResultModel;

                if (resultValue is null || resultValue.code != "0")
                {
                     AgvInfoChange?.Invoke(null, reqCode, eqCode);
                    return;
                }
                AgvInfoChange?.Invoke(resultValue.data, reqCode, eqCode);
            });
        }

        private async Task CreatRcsServiceModelAsync(RcsDto info)
        {
            if (info.status != 1) return;
            var model = _mapper.Map<RcsServiceModel>(info);
            if (model is null) return;
            var apiInfos = await _rcsApiService.QueryRcsApiBaseRcsIdAsync(model.id);
            List<Task<RcsApiModel>> apiAdd = new();
            if (apiInfos is not null)
            {
                foreach (var api in apiInfos)
                {
                    apiAdd.Add(GetApiModel(api));
                }
                await Task.WhenAll(apiAdd);
                model.apiInfos = apiAdd.Where(a => a.Result is not null)?.Select(a => a.Result).ToList();
            }
            var flag = RcsInfo.TryAdd(info.rcs, model);

        }
        private async Task<RcsApiModel> GetApiModel(RcsApiDto dto)
        {
            return await Task.Run(() => 
            {
               return _mapper.Map<RcsApiModel>(dto);
            });
        }
        /// <summary>
        /// 查询rcs的api信息
        /// </summary>
        /// <param name="rcs"></param>
        /// <param name="api"></param>
        /// <returns></returns>
        private async Task<string> QueryRcsApi(string rcs, string api)
        {
            var flag = RcsInfo.TryGetValue(rcs, out RcsServiceModel? model);
            if (!flag || model is null)
            {
                return null;
            }
            var apiinfo = model.apiInfos?.FirstOrDefault(a => a.WCSDomainName == api);
            if (apiinfo is null)
            { 
                return null; 
            }
            return apiinfo.apiName;
        }
        private string GetreqCode() => Guid.NewGuid().ToByteArray().Aggregate<byte, long>(1, (current, b) => current * (b + 1)).ToString();
        #endregion

        #region WCSRCS参数创建
        /// <summary>
        /// 创建wcs返回Rcs参数
        /// </summary>
        /// <param name="api"></param>
        /// <param name="data"></param>
        /// <returns></returns>
        private async Task<(string, object)> CreatWcsResultRcsPara(string api, object data)
        {
            return await Task.Run(() => 
            {
                object result = null;
                string reqCode = "";
                switch (api)
                {
                    case ConstStringData.ChargeReport_WCSApi:
                        (result, reqCode) = _rcsApiBuildService.CreatChargeRequestResultModel(data);
                        break;
                }

                return (reqCode, result);
            });
        }

        private async Task<object> CreatWcsRcsPara(string api,object data)
        {
            var para = await Task.Run(() =>
            {
                object result = null;
                switch (api)
                {
                    case ConstStringData.CreatTask_WCSApi:
                        result = _rcsApiBuildService.CreatTask(data);
                        break;
                    case ConstStringData.ContinueTask_WCSApi:
                        result = _rcsApiBuildService.CreatContinueTask(data);
                        break;
                    case ConstStringData.CancelTask_WCSApi:
                        result = _rcsApiBuildService.CreatCancelTask(data);
                        break;
                    case ConstStringData.SetTaskPriority_WCSApi:
                        result = _rcsApiBuildService.CreatSetPriority(data);
                        break;
                    case ConstStringData.BindPodAndBerth_WCSApi:
                        result = _rcsApiBuildService.CreatBindPodAndBerth(data);
                        break;
                    case ConstStringData.BindPodAndMat_WCSApi:
                        result = _rcsApiBuildService.CreatBindPodAndMat(data);
                        break;
                    case ConstStringData.LockPosition_WCSApi:
                        result = _rcsApiBuildService.CreatLockPosition(data);
                        break;
                    case ConstStringData.SyncMapDatas_WCSApi:
                        result = _rcsApiBuildService.CreatSyncMapDatas(data);
                        break;
                    case ConstStringData.QueryPodBerthAndMat_WCSApi:
                        result = _rcsApiBuildService.CreatQueryPodBerthAndMat(data);
                        break;
                    case ConstStringData.BlockStgBin_WCSApi:
                        result = _rcsApiBuildService.CreatBlockStgBin(data);
                        break;
                    case ConstStringData.BindCtnrAndBin_WCSApi:
                        result = _rcsApiBuildService.CreatBindCtnrAndBin(data);
                        break;
                    case ConstStringData.QueryTaskStatus_WCSApi:
                        result = _rcsApiBuildService.CreatQueryTaskStatus(data);
                        break;
                    case ConstStringData.QueryAgvStatus_WCSApi:
                        result = _rcsApiBuildService.CreatQueryAgv(data);
                        break;
                    case ConstStringData.StopRobot_WCSApi:
                        result = _rcsApiBuildService.CreatStopAgv(data);
                        break;
                    case ConstStringData.ResumeRobot_WCSApi:
                        result = _rcsApiBuildService.CreatRecoveryAgv(data);
                        break;
                    case ConstStringData.BlockArea_WCSApi:
                        result = _rcsApiBuildService.CreatBlockArea(data);
                        break;
                    case ConstStringData.GenPreScheduleTask_WCSApi:
                        result = _rcsApiBuildService.CreatPreScheduleTaskModel(data);
                        break;
                    case ConstStringData.ClearRoadWay_WCSApi:
                        result = _rcsApiBuildService.CreatClearRoadWay(data);
                        break;
                    case ConstStringData.GetOutPod_WCSApi:
                        result = _rcsApiBuildService.CreatGetOutPod(data);
                        break;
                    case ConstStringData.ReturnPod_WCSApi:
                        result = _rcsApiBuildService.CreatReturnPod(data);
                        break;
                    case ConstStringData.GenCtuGroupTaskBatc_WCSApi:
                        result = _rcsApiBuildService.CreatGenCtuGroupTaskBatch(data);
                        break;
                    case ConstStringData.BoxApplyPass_WCSApi:
                        result = _rcsApiBuildService.CreatBoxApplyPass(data);
                        break;
                    case ConstStringData.BindMaterialTypCodeAndBerth_WCSApi:
                        result = _rcsApiBuildService.CreatbindMaterialTypCodeAndBerth(data);
                        break;
                };
                return result;
            });

            return para;
        }
        #endregion

        #region AGV外设控制参数创建
        /// <summary>
        /// 滚筒数据创建
        /// </summary>
        /// <param name="para"></param>
        /// <returns></returns>
        private async Task<string> CreatRollerParaAsync(object para)
        {
            return await Task.Run(() => 
            {
                var model = para as RollerOpticalModel;
                if (model is null)
                {
                    return null;
                }
                return JsonConvert.SerializeObject(model);
            });
            
        }
        /// <summary>
        /// 指示灯数据创建
        /// </summary>
        /// <param name="para"></param>
        /// <returns></returns>
        private async Task<string> CreatPromptlightParaAsync(object para)
        {
            return await Task.Run(() => 
            {
                var model = para as PromptlightOpticalModel;
                if (model is null)
                {
                    return null;
                }
                return JsonConvert.SerializeObject(model);
            });
        }
        #endregion
    }
}
